﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace OpenLightGroup.Common.Interactivity
{
    /// <summary>
    /// An action that will show a ChildWindow control when triggered.
    /// </summary>
    [Description("Will show the ChildWindow when triggered.")]
    public class ShowChildWindowAction
    : TriggerAction<FrameworkElement>
    {
        /// <summary>
        /// The ChildWindow control to show. This can be any control that inherits from ChildWindow.
        /// </summary>
        public ChildWindow ChildWindow
        {
            get
            {
                return (ChildWindow)this.GetValue(ChildWindowProperty);
            }
            set
            {
                this.SetValue(ChildWindowProperty, value);
            }
        }

        /// <summary>
        /// DependencyProperty backing store for the ChildWindow object.
        /// </summary>
        public static readonly DependencyProperty ChildWindowProperty =
        DependencyProperty.Register("ChildWindow", typeof(ChildWindow), typeof(ShowChildWindowAction), new PropertyMetadata(null));

        /// <summary>
        /// Attaches this object to the DataContext property of the ChildWindow when it is shown.
        /// </summary>
        [Description("Attaches this object to the DataContext of the ChildWindow")]
        public object DataContext
        {
            get
            {
                return this.GetValue(DataContextProperty);
            }
            set
            {
                this.SetValue(DataContextProperty, value);
            }
        }

        /// <summary>
        /// DependencyProperty backing store for the DataContext property.
        /// </summary>
        public static readonly DependencyProperty DataContextProperty =
        DependencyProperty.Register("DataContext", typeof(object), typeof(ShowChildWindowAction), new PropertyMetadata(null));



        /// <summary>
        /// Determines if the ClosedCommand should be executed regardless of the DialogResult.
        /// </summary>
        [DefaultValue(false)]
        [Description("Execute ClosedCommand regardless of the DialogResult value")]
        public bool ExecuteCommandOnCancel { get; set; }

        /// <summary>
        /// Command to execute when the ChildWindow is closed. Will only execute if the DialogResult is true or ExecuteCommandOnCancel is true.
        /// </summary>
        [Description("Command to execute when the window is closed.")]
        public ICommand ClosedCommand
        {
            get
            {
                return (ICommand)this.GetValue(ClosedCommandProperty);
            }
            set
            {
                this.SetValue(ClosedCommandProperty, value);
            }
        }

        /// <summary>
        ///  DependencyProperty backing store for the ClosedCommand Property
        /// </summary>
        public static readonly DependencyProperty ClosedCommandProperty =
        DependencyProperty.Register("ClosedCommand",
                                    typeof(ICommand),
                                    typeof(ShowChildWindowAction),
                                    new PropertyMetadata(null));

        /// <summary>
        /// The name of the ChildWindow's property to use as the parameter of the closed command.
        /// </summary>
        [Description("The name of the child window's property to use as the parameter of the closed command.")]
        public string CommandParameter
        {
            get
            {
                return (string)this.GetValue(CommandParameterProperty);
            }
            set
            {
                this.SetValue(CommandParameterProperty, value);
            }
        }

        /// <summary>
        ///  DependencyProperty backing store for the CommandParameter Property
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(string), typeof(ShowChildWindowAction), new PropertyMetadata(null));

        /// <summary>
        /// Method to handle initializing and showing the ChildWindow
        /// </summary>
        protected override void Invoke(object parameter)
        {
            if (this.ChildWindow != null)
            {

                Binding dataContextBinding = new Binding("DataContext");

                dataContextBinding.Source = this;

                this.ChildWindow.SetBinding(ChildWindow.DataContextProperty, dataContextBinding);

                if (this.ClosedCommand != null)
                    this.ChildWindow.Closed += new EventHandler(window_Closed);

                this.ChildWindow.Show();

            }

        }

        private void window_Closed(object sender, EventArgs e)
        {

            ChildWindow window = (ChildWindow)sender;

            this.ChildWindow.Closed -= new EventHandler(window_Closed);

            if (this.ClosedCommand != null &&
                 (this.ExecuteCommandOnCancel ||
                   (window.DialogResult.HasValue && window.DialogResult.Value == true)))
            {

                object param = null;

                if (this.GetValue(ShowChildWindowAction.CommandParameterProperty) != null)
                {
                    param = this.GetValue(ShowChildWindowAction.CommandParameterProperty);
                }

                this.ClosedCommand.Execute(param);

            }

        }
    }
}